/**
 * ajax 请求
 * Created by Administrator on 2017-08-11.
 */

import axios from 'axios'

const METHOD_GET = 'GET'
const METHOD_POST = 'POST'
const METHOD_PUT = 'PUT'
const METHOD_DELETE = 'DELETE'



let lockMap = {}

/**
 * 错误提示
 * @type {Function}
 */
function showError(message) {
  (global.showError || global.alert)(message)
}

/**
 * 是否为数组
 */
function isArray(v) {
  return toString.apply(v) === '[object Array]'
}

/**
 * 编码请求参数
 * @param val
 * @param pctEncodeSpaces
 * @returns {string}
 */
function encodeUriQuery(val, pctEncodeSpaces) {
  return encodeURIComponent(val)
    .replace(/%40/gi, '@')
    .replace(/%3A/gi, ':')
    .replace(/%24/g, '$')
    .replace(/%2C/gi, ',')
    .replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'))
    .replace(/'/g, '%27')
}

/**
 * 请求数据格式化
 * @param {Object} urlOld
 * @param {Object} paramData
 * @param {Object} method
 */
function httpUrlFormat(urlOld, paramData, method) {
  if (paramData) {
    var urlArray = []

    paramData = isArray(paramData) ? (paramData.length > 0 ? paramData[0] : []) : paramData
    for (var key in paramData) {
      var value = paramData[key]
      if (isArray(value)) {
        if (method.toUpperCase() === 'GET' || method.toUpperCase() === 'DELETE') {
          var arrayValueCell = []
          for (var keyCell in value) {
            var valueCell = value[keyCell]
            arrayValueCell.push(key + '=' + encodeUriQuery(valueCell))
          }
          if (arrayValueCell.length > 0) {
            urlArray.push(arrayValueCell.join('&'))
          }
        }
      } else {
        if (urlOld.indexOf(':' + key, value) !== -1) {
          urlOld = urlOld.replace(':' + key, encodeUriQuery(value))
        } else {
          if (method.toUpperCase() === 'GET' || method.toUpperCase() === 'DELETE') {
            urlArray.push(key + '=' + encodeUriQuery(value))
          }
        }
      }
    }

    urlArray.sort(function (a, b) {
      return a.localeCompare(b)
    })
    urlOld = encodeURI(urlOld) + (urlArray.length > 0 ? ('?' + urlArray.join('&')) : '')
  } else {
    urlOld = encodeURI(urlOld)
  }
  return (urlOld)
}


/**
 * 参数重组
 * @param args
 */
function rebuild(args) {
  var config = {};
  if (args.length === 1) {
    if (typeof args[0] === 'string') {
      config.url = args[0]
    }
    else {
      config = args[0]
    }
  } else if (args.length === 2) {
    config = args[1] ? args[1] : {}
    config.url = args[0]
  }
  else if (args.length === 3) {
    config = args[2] ? args[2] : {}
    config.url = args[0]
    if (args[1] !== null) {
      config.data = args[1]
    }
  }
  return config
}

var Http = {
  get: function () {
    var config = rebuild(arguments)
    config.method = METHOD_GET
    return Http.execute(config)
  },
  post: function () {
    var config = rebuild(arguments)
    config.method = METHOD_POST
    return Http.execute(config)
  },
  put: function () {
    var config = rebuild(arguments)
    config.method = METHOD_PUT
    return Http.execute(config)
  },
  delete: function () {
    var config = rebuild(arguments)
    config.method = METHOD_DELETE
    return Http.execute(config)
  },
  upload: function () {
    var config = rebuild(arguments)
    config.method = METHOD_POST
    return Http.doUpload(config)

  },
  /**
   * 下载
   */
  download: function () {
    var config = rebuild(arguments)
    config.method = METHOD_GET
    return Http.execDownload(config)
  },
  execute: function (config) {
    // 使用Promise 处理成功
    if (config.success == null) {
      return new Promise(function (resolve, reject) {
        config.success = function (res) {
          resolve(res)
        }
        if (config.customReject) {
          config.reject = function (err) {
            reject(err)
          }
        }
        else {
          config.commonReject = function (err) {
            reject(err)
          }
        }

        Http.doExecute(config)
      })
    } else {
      return Http.doExecute(config)
    }
  },
  doExecute: function (config) {

    config.method = (config.method || config.type || METHOD_GET).toUpperCase()

    // 设置头部
    config.headers = config.header || config.headers || {}
    // 普通表单方式提交
    if (config.form && config.method === METHOD_POST) {
      config.headers['Content-Type'] = config.headers['Content-Type'] || 'application/x-www-form-urlencoded'
    }
    else {
      config.headers['Content-Type'] = config.headers['Content-Type'] || 'application/json'
    }
    /**
     * 设置平台信息
     */
    config.headers['platform'] = 'mini_program';

    config.headers['x-app'] = global.APP_ID;

    let timestamp = Math.floor(new Date().getTime() / 1000);

    config.headers['x-timestamp'] = timestamp;


    Http.combine(config)

    let lockKey = config.method + '#' + config.url + '#' + JSON.stringify(config.data || {});
    //非GET 对请求加锁处理
    if (config.method != METHOD_GET) {
      if (lockMap[lockKey]) {
        console.log("重复请求：" + lockKey, lockMap);
        return;
      }
      lockMap[lockKey] = true
    }



    // 成功回调
    var successCallback = config.success || function (response, status, header, config) { }

    // 失败回调
    var errorCallback = config.fail || config.error || function (response, status, header) {
      if (config.ignore) {
        return
      }
      if (response && response.message) {
        showError(response.message)
      }
    }

    // 处理错误
    let handleFail = (response) => {
      let statusCode = response.status;
      let data = response.data;
      if (statusCode == 401) {
        TokenManager.clear();
      }
      if ((statusCode == 401) && !config.anonymous) {
        config.reject && config.reject(data)
        config.commonReject && config.commonReject(data)
        global.login();
      }
      else {
        if (data && !data.message) {
          data.message = data.msg || '请求失败';
        }

        // 自定义reject处理
        if (config.reject) {
          config.reject(data);
          return;
        }


        if (data && data.message) {
          errorCallback(data, statusCode, response.header)
          config.commonReject && config.commonReject(data)
        }
        else if (!config.anonymous) {
          showError('请求失败');

        }
      }
    }

    //请求完成回调
    var completeCallback = config.complete || function (res) {
      if (config.loading !== false) {
        global.hideLoading();
      }
    }


    

    config.success = function (response) {
      
      let statusCode = response.status;
      let data = response.data;
      if (data && data.code) {
        if (typeof data.code == 'number') {
          statusCode = data.code;
        }
      }
      if (data && data['x-data']) {
        let xData = data['x-data'];
        let xSign = data['x-signature'];
        data = encrypt.decryptLong(xData);
        data = JSON.parse(decodeURIComponent(data));
        let xTimestamp = data['x-timestamp'];
        delete data['x-timestamp'];
      }

      if (statusCode == 200) {

        successCallback(data);
        
      }
      else {
        handleFail(response);
      }
    }

    config.fail = config.fail || function (response) {
      handleFail(response);
    }

    config.complete = function (res) {
      delete lockMap[lockKey]
      completeCallback(res);
    }

    if (config.url.indexOf('http') !== 0) {
      config.url = config.baseURL + config.url;
    }


    axios(config).then(function (result) {
      config.success(result);
      config.complete();
    }).catch(function (error) {
      config.fail(error.response)
      config.complete();
    })
  },
  /**
   * 执行上传
   */
  doUpload: function (config) {
    // 设置头部
    config.headers = config.header || config.headers || {}
    /**
     * 设置平台信息
     */

    config.headers['platform'] = 'mini_program';


    config.headers['x-app'] = global.APP_ID;

    Http.combine(config)


    // 成功回调
    var successCallback = config.success || function (response, status, header, config) { }

    // 失败回调
    var errorCallback = config.fail || config.error || function (response, status, header) {
      if (config.ignore) {
        return
      }
      if (response && response.message) {
        showError(response.message)
      }
    }

    //请求完成回调
    var completeCallback = config.complete || function (res) {
      if (config.loading !== false) {
        global.hideLoading();
      }
    }

    config.success = function (response) {
      console.log(response)
      if (response.statusCode == 200) {
        successCallback(response.data);
      }
      else {
        if (response.statusCode == 401){
            //TokenManager.clear();
        }
        if ((response.statusCode == 401) && !config.anonymous) {
          global.login();
        }
        else {
          if (response && response.data && response.data.message) {
            errorCallback(response.data, response.statusCode, response.header)
          }
          else if(!config.anonymous){
            showError('请求失败');
          }
        }
      }
    }

    config.fail = config.fail || function (res) {
      showError('请求失败，请检查网络或参数')
    }

    config.complete = function (res) {
      completeCallback(res);
    }
    config.formData = config.formData || config.data;
    delete config.data;

    if (config.url.indexOf('http') !== 0) {
      config.url = config.baseURL + config.url;
    }

    axios(config).then(function (result) {
      config.success(result.data);
      config.complete();
    }).catch(function (error) {
      config.fail(error.response)
      config.complete();
    })
  },


  /**
   * 数据合并
   * @param config
   */
  combine: function (config) {
    // 替换路径占位符号
    if (config.path) {
      for (var key in config.path) {
        config.url = config.url.replace('{' + key + '}', config.path[key])
      }
      delete config.path
    }
    config.data = config.data || config.body || config.form;


    var isFormData = config.isFormData
    if (!isFormData) {
      // 过滤掉null数据
      var data = config.data;
      var method = config.method
      if (config.query) {
        data = config.query
        method = METHOD_GET
      }
      config.data = Http.filter(config.data)
      data = Http.filter(data)
      config.url = httpUrlFormat(config.url, data, method)
    }
    // 非http开头的加上API_BASE_PATH
    if (config.url.indexOf('http') !== 0) {
      if (!global.API_BASE_PATH) {
        throw new Error('请配置接口基本地址global.API_BASE_PATH')
      }
      config.baseURL = global.API_BASE_PATH
    }
    delete config.body
    delete config.query
    delete config.form
  },
  filter: function (data) {
    if (Object.prototype.toString.call(data) === '[object Array]') {
      for (let i = 0; i < data.length; i++) {
        data[i] = Http.filter(data[i]);
      }
      return data;
    }

    var _data = {}
    for (var i in data) {
      var val = data[i]
      if (val === null || typeof val === 'undefined') {
        continue
      }

      _data[i] = val
    }
    return _data
  },
  /**
   * 组装请求头
   * @param {Object} config
   */
  combineHeaders(config) {

    // 设置头部
    config.headers = config.header || config.headers || {}

    config.baseURL = global.API_BASE_PATH

    /**
     * 设置平台信息
     */

    config.headers['app-version'] = global.APP_VERSION;
    config.headers['platform'] = 'mini_program';

    config.headers['x-app'] = global.APP_ID;

    // 参数组装
    Http.combine(config)


  }

}
export default Http

